package com.scm.common.utils;

import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by houchen on 16/8/19.
 */
public class TOTransferHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(TOTransferHelper.class);

    /**
     *通过json序列化的方式，实现对象属性copy。
     *注:因为要先序列化源对象,把不需要序列化的属性设置@JSONField(serialize=false)!!!
     * @param tos
     * @param clazz
     * @param <D>
     * @param <T>
     * @return
     */
    public static <T> List<T> trans(List<T> tos, Class<T> clazz) {
        return trans2TO(tos, clazz);
    }

    /**
     *通过json序列化的方式，实现对象属性copy。
     *注:因为要先序列化源对象,把不需要序列化的属性设置@JSONField(serialize=false)!!!
     * @param to
     * @param clazz
     * @param <D>
     * @param <T>
     * @return
     */
    public static <T> T trans(T to, Class<T> clazz) {
        return trans2TO(to, clazz);
    }

    /**
     *通过json序列化的方式，实现对象属性copy。
     *注:因为要先序列化源对象,把不需要序列化的属性设置@JSONField(serialize=false)!!!
     * @param domains
     * @param clazz
     * @param <D>
     * @param <T>
     * @return
     */
    public static <D, T> List<T> trans2TO(List<D> domains, Class<T> clazz) {
        if (CollectionUtils.isEmpty(domains))
            return Collections.emptyList();

        List<T> tos = new ArrayList<>(domains.size());
        domains.forEach(o -> {
            T to = trans2TO(o, clazz);
            tos.add(to);
        });
        return tos;
    }

    /**
     *通过json序列化的方式，实现对象属性copy。
     * 注:因为要先序列化源对象,把不需要序列化的属性设置@JSONField(serialize=false)!!!
     * @param domain
     * @param clazz
     * @param <D>
     * @param <T>
     * @return
     */
    public static <D, T> T trans2TO(D domain, Class<T> clazz) {
        T to = (T) newT(clazz);
        String json = new Gson().toJson(domain);
        to = new Gson().fromJson(json, clazz);
        return to;
    }

    private static <T> T newT(Class<T> clazz) {
        T t = null;
        try {
            t = clazz.newInstance();
        } catch (InstantiationException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (IllegalAccessException e) {
            LOGGER.error(e.getMessage(), e);
        }
        return t;
    }

    /**
     *
     * 把from的属性值复制到to
     * 注:使用spring的属性copy，先读取目标对象字段，再读取源对象属性。性能较好
     * @param from
     * @param to
     * @param <FROM>
     * @param <TO>
     */
    public static <FROM, TO> void trans(FROM from, TO to) {
        try {
            BeanUtils.copyProperties(from, to);
        } catch (BeansException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }
}
